package alipay

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"sort"
	"time"

	"gitee.com/golangx/util"
)

var appID, publicKey, privateKey string

// URL 支付宝请求地址
//var URL = "https://openapi.alipay.com/gateway.do"
var URL = "https://openapi.alipaydev.com/gateway.do"

// New 初始化公私钥和签名变量
func New(alipayAppID, alipayPublicKey, alipayPrivateKey string) {
	appID = alipayAppID
	publicKey = alipayPublicKey
	privateKey = alipayPrivateKey
}

// paramsFill 填充公共参数
func paramsFill(methodName, bizContent string) map[string]string {
	publicParams := make(map[string]string)
	publicParams["app_id"] = appID
	publicParams["charset"] = "utf-8"
	publicParams["sign_type"] = "RSA2"
	publicParams["timestamp"] = time.Now().Format("2006-01-02 15:04:05")
	publicParams["version"] = "1.0"
	publicParams["method"] = methodName
	publicParams["biz_content"] = bizContent
	return publicParams
}

// sign 获得从参数列表拼接而成的待签名字符串
// mapBody：是我们从HTTP request body parse出来的参数的一个map
// 返回值：sign是拼接好排序后的待签名字串。
func signSrc(mapBody map[string]string) string {
	sortedKeys := make([]string, 0)
	for k := range mapBody {
		sortedKeys = append(sortedKeys, k)
	}
	sort.Strings(sortedKeys)
	var src string

	index := 0
	for _, k := range sortedKeys {
		value := fmt.Sprintf("%v", mapBody[k])
		if value != "" {
			src = src + k + "=" + value
		}
		//最后一项后面不要&
		if index < len(sortedKeys)-1 {
			src = src + "&"
		}
		index++
	}
	return src
}

// Callback 支付宝支付异步回调处理
func Callback(r *http.Request) {
	//body就是支付宝给我们的参数字符串
	paramerStr, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	fmt.Println("ordeCallback", string(paramerStr))
	//调用url.ParseQuery来获取到参数列表，url.ParseQuery还会自动做url safe decode
	valuesM, err := url.ParseQuery(string(paramerStr))
	if err != nil {
		log.Println("ordeCallback", string(paramerStr))
		err = fmt.Errorf("回调参数解析错误:%v", err)
		return
	}
	var m map[string]string
	m = make(map[string]string)
	for k, v := range valuesM {
		if k == "sign" || k == "sign_type" { //不要'sign'和'sign_type'
			continue
		}
		m[k] = v[0]
	}

	sign := valuesM["sign"][0]

	//获取要进行计算哈希的sign string
	src := signSrc(m)
	//进行rsa验签
	ok, err := util.RSACheck(src, sign, publicKey)
	if !ok {
		fmt.Println("verify sig not pass. error:", err)
	}
}

func trade(method, bizContent string) (body []byte, err error) {
	params := paramsFill(method, bizContent)
	src := signSrc(params)
	sign, err := util.RSA(src, privateKey)
	if err != nil {
		err = fmt.Errorf("%s 生成支付宝签名错误, 原因: %v", method, err)
		return
	}
	params["sign"] = sign
	postValues := url.Values{}
	for k, v := range params {
		postValues[k] = []string{v}
	}
	resp, err := http.PostForm(URL, postValues)
	if err != nil {
		err = fmt.Errorf("请求支付宝退款接口失败: %v", err)
		return
	}
	defer resp.Body.Close()
	body, err = ioutil.ReadAll(resp.Body)
	return
}
